package service

import (
	"fmt"
	"gitee.com/filters/logger"
	"gitee.com/filters/starter/config"
	"gitee.com/filters/utils/conversion"
	"github.com/robfig/cron/v3"
	"github.com/spf13/viper"
	"google.golang.org/grpc"
	"google.golang.org/grpc/reflection"
	"net"
	"reflect"
)

const (
	GrpcConfigKey = "grpcserver"
)

type GrpcServer struct {
	srvMap     []GrpcCfgMap
	config     *viper.Viper
	grpcConfig *config.GrpcConfig
}
type GrpcCfgMap struct {
	Srv
	Service
	SrvDesc
}

func (g *GrpcServer) SetGrpcConfig(es *config.GrpcConfig) {
	g.grpcConfig = es
}

func (g *GrpcServer) GetGrpcConfig() *config.GrpcConfig {
	return g.grpcConfig
}

func (g *GrpcServer) SetConfig(es *viper.Viper) {
	g.config = es
}

func (g *GrpcServer) GetConfig() *viper.Viper {
	return g.config
}

func (g *GrpcServer) SetMap(es []GrpcCfgMap) {
	g.srvMap = es
}

func (g *GrpcServer) GetMap() []GrpcCfgMap {
	return g.srvMap
}

type Srv any
type Service any
type SrvDesc any

func NewGrpc(srvMap []GrpcCfgMap) *GrpcServer {
	s := &GrpcServer{}
	conf, err := config.LoadConfig(&config.ConfigMap{})
	if err != nil {
		panic(err)
	}
	s.SetMap(srvMap)
	s.SetConfig(conf)
	return s
}

// UseLog 日志记录
func (g *GrpcServer) UseLog() *GrpcServer {
	var logx config.GinLog
	if err := g.GetConfig().UnmarshalKey(logger.Logger, &logx); err != nil {
		panic(err)
	}
	logger.NewLog(logger.WithWritePath(logx.LogFilePath),
		logger.WithLogExt(logx.LogFileExt)).CurLog().WrapFormat()
	return g
}

// BindField 绑定数据
func (g *GrpcServer) BindField(f ...interface{}) *GrpcServer {
	for _, i2 := range f {
		conversion.ToStruct(g.GetConfig().AllSettings(), i2)
	}
	return g
}

// HandleAddFunc 定时执行函数
func (g *GrpcServer) HandleAddFunc(list []*config.CronTabObj) *GrpcServer {
	c := cron.New(cron.WithSeconds())
	for index, crontabObj := range list {
		func(id int, obj *config.CronTabObj) {
			_, _ = c.AddJob(
				obj.CronTab, //一分钟
				cron.FuncJob(func() {
					_ = obj.Handler()
				}))
		}(index, crontabObj)
	}
	c.Start() //启动crond
	return g
}

func (g *GrpcServer) Run() error {
	fmt.Println("grpc server start")
	var grpcx config.GrpcConfig
	if err := g.GetConfig().UnmarshalKey(GrpcConfigKey, &grpcx); err != nil {
		panic(err)
	}
	g.SetGrpcConfig(&grpcx)
	lis, err := net.Listen("tcp", fmt.Sprintf("127.0.0.1:%d", grpcx.GrpcPort))
	if err != nil {
		return err
	}

	conn := grpc.NewServer()
	for _, v := range g.srvMap {
		// 反射注册Grpc服务
		ss := reflect.ValueOf(v.Srv)
		args := []reflect.Value{reflect.ValueOf(conn), reflect.ValueOf(v.Service)}
		ss.Call(args)
	}
	// 往grpc服务端注册反射服务
	reflection.Register(conn)
	fmt.Printf("grpc server:%s \n", fmt.Sprintf("http://127.0.0.1:%d", grpcx.GrpcPort))
	// 启动grpc服务
	if err := conn.Serve(lis); err != nil {
		return err
	}
	return nil
}
